/******************************************************************************
* FILE: 09-mutex.c
* DESCRIPTION:
*   This is a simple serial program which computes the dot product of two 
*   vectors.  The threaded version is 10-mutex.c.
* SOURCE: Vijay Sonnad, IBM
* LAST REVISED: 01/29/09 Blaise Barney
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>

/*   
     The following structure contains the necessary information  
     to allow the function "dotprod" to access its input data and 
     place its output so that it can be accessed later. 
*/

typedef struct {
   double *a;
   double *b;
   double sum; 
   int veclen; 
} DOTDATA;

#define VECLEN 100000
DOTDATA dotstr; 

/*
  We will use a function (dotprod) to perform the scalar product. 
  All input to this routine is obtained through a structure of 
  type DOTDATA and all output from this function is written into
  this same structure.  While this is unnecessarily restrictive 
  for a sequential program, it will turn out to be useful when
  we modify the program to compute in parallel.
*/

void dotprod() {

   /* Define and use local variables for convenience */
   int start, end, i, j; 
   double mysum, *x, *y;

   start=0;
   end = dotstr.veclen;
   x = dotstr.a;   /* one vector */
   y = dotstr.b;   /* second vector */

   /*
     Perform the dot product and assign result
     to the appropriate variable in the structure. 
   */

   for (j=0 ; j < 2000 ; j++) {
      mysum = 0;
      for (i=start ; i < end ; i++) mysum += (x[i] * y[i]);
      dotstr.sum = mysum;
   }
}

/*
  The main program initializes data and calls the dotprd() function.
  Finally, it prints the result.
*/

int main (int argc, char *argv[]) {
   int i,len;
   double *a, *b;

   unsigned long mask = 15; /* select all processors */
   
   /* bind process to processor 0 */
   if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
      perror("pthread_setaffinity_np");
   }

   /* Assign storage and initialize values */
   len = VECLEN;
   a = (double*) malloc(len*sizeof(double));
   b = (double*) malloc(len*sizeof(double));
   
   for (i=0 ; i < len ; i++) a[i] = b[i] = 1;

   dotstr.veclen = len; 
   dotstr.a = a; 
   dotstr.b = b; 
   dotstr.sum=0;

   /* Perform the  dotproduct */
   dotprod ();

   /* Print result and release storage */ 
   printf ("Sum =  %f \n", dotstr.sum);
   free (a);
   free (b);
}
